<route lang="json5">
{
  style: {
    navigationBarTitleText: '聊天',
    navigationStyle: 'custom',
  },
}
</route>

<template>

    <view>

      <!-- 消息区 -->
      <scroll-view
        style="height: calc(100dvh - 166px);"
        scroll-y
        :scroll-into-view="scrollIntoView"
        :scroll-with-animation="true"
        :refresher-enabled="true"
        :refresher-triggered="refresher"
        refresher-background="#f7f8fa"
      >

        <transition-group name="fade" tag="view">
          <view v-for="msg in messages" :key="msg.id" :id="msg.id" class="mb-3">

            <!-- 日期分割线 -->
            <view v-if="msg.type === 'divider'" class="flex items-center justify-center my-3">
              <view class="text-xs text-gray-500 bg-white/70 backdrop-blur px-3 py-1 rounded-full shadow">
                {{ msg.label }}
              </view>
            </view>

            <!-- 文本消息 -->
            <view v-else-if="msg.type === 'text'" class="flex items-end" :class="msg.from === 'me' ? 'justify-end' : 'justify-start'">
              <image v-if="msg.from !== 'me'" class="w-8 h-8 rounded-full mr-2" src="/static/chat/avatar-bot.png" mode="aspectFill" />
              <view :class="[
                    'bubble max-w-[80%] p-3 rounded-2xl shadow-sm',
                    msg.from === 'me'
                      ? 'from-me bg-gradient-to-br from-blue-500/90 to-blue-600/90 text-white'
                      : 'from-bot bg-white'
                  ]">
                <text class="text-[15px] leading-[22px] whitespace-pre-wrap break-words">{{ msg.text }}</text>
                <view class="mt-1 text-[10px] opacity-70 text-right">{{ formatTime(msg.time) }}</view>
              </view>
              <image v-if="msg.from === 'me'" class="w-8 h-8 rounded-full ml-2" src="/static/chat/avatar-me.png" mode="aspectFill" />
            </view>

            <!-- 打字中 -->
            <view v-else-if="msg.type === 'typing'" class="flex justify-start items-end">
              <image class="w-8 h-8 rounded-full mr-2" src="/static/avatar-bot.png" mode="aspectFill" />
              <view class="bubble bg-white max-w-[70%] p-3 rounded-2xl shadow-sm">
                <view class="typing">
                  <view class="dot"></view>
                  <view class="dot"></view>
                  <view class="dot"></view>
                </view>
              </view>
            </view>

            <!-- 学习资源卡片轮播 -->
            <view v-else-if="msg.type === 'resources'" class="my-4">
              <swiper
                class="w-full h-48 rounded-2xl overflow-hidden"
                circular
                indicator-dots
                autoplay
                :interval="4000"
              >
                <swiper-item
                  v-for="(res, i) in msg.resources"
                  :key="i"
                  @click="openLink(res.link)"
                >
                  <view class="h-full p-0">
                    <view class="h-24 relative">
                      <image v-if="res.cover" :src="res.cover" class="w-full h-full object-cover" mode="aspectFill"/>
                      <view v-else class="w-full h-full bg-gradient-to-br from-slate-100 to-slate-200"/>
                      <view class="absolute inset-0 bg-black/10"/>
                    </view>
                    <view class="bg-white h-24 p-3 shadow-sm">
                      <view class="font-semibold text-[15px] mb-1 line-clamp-1">{{ res.title }}</view>
                      <view class="text-[12px] text-gray-600 line-clamp-2">{{ res.description }}</view>
                      <view class="mt-2 text-[12px] text-blue-600">点击查看 →</view>
                    </view>
                  </view>
                </swiper-item>
              </swiper>
              <view class="mt-1 text-center text-[10px] text-gray-400">{{ formatTime(msg.time) }}</view>
            </view>
          </view>
        </transition-group>

        <!-- 底部锚点 -->
        <view :id="bottomAnchorId"></view>
      </scroll-view>

      <!-- 输入区 -->
      <view class="composer border-t border-gray-200 bg-white"
          :style="{ paddingBottom: 'calc(env(safe-area-inset-bottom) + 8px)' }">

      <!-- 工具区：表情/快捷短语 -->
      <view class="tools-row">
        <wd-button class="wd-tool-btn" size="small" plain
                  @click="quickInsert('😊')">😊</wd-button>
        <wd-button class="wd-tool-btn" size="small" plain
                  @click="quickInsert('学习资源')">资源</wd-button>
      </view>

      <!-- 主输入区：多行输入 + 发送 -->
      <view class="composer-main">
        <textarea
          v-model="input"
          class="composer-input"
          placeholder="请输入消息…"
          :show-confirm-bar="false"
          auto-height
          @confirm="sendMessage"
          confirm-type="send"
        />
        <wd-button
          class="wd-send-btn"
          type="primary"
          size="small"
          :loading="sending"
          :disabled="sending || !input.trim()"
          @click="sendMessage"
        >
          {{ sending ? '发送中…' : '发送' }}
        </wd-button>
      </view>
</view>
    </view>
</template>

<script lang="ts" setup>
import { ref, nextTick, onMounted } from 'vue'
import { chatMessagesPost, chatConversationsPost, messagesGet } from '@/api/allApi'

type From = 'me' | 'bot'
type BaseMsg = { id: string; from: From; time: number }
type TextMsg = BaseMsg & { type: 'text'; text: string }
type ResItem = { title: string; description: string; link: string; cover?: string }
type ResMsg = BaseMsg & { type: 'resources'; resources: ResItem[] }
type DividerMsg = { id: string; type: 'divider'; label: string }
type TypingMsg = { id: string; type: 'typing' }
type Message = TextMsg | ResMsg | DividerMsg | TypingMsg

// 安全区域信息
const { safeAreaInsets } = uni.getSystemInfoSync()

const conversationId = ref()

const input = ref('')
const sending = ref(false)
const refresher = ref(false)

const bottomAnchorId = 'bottom'
const scrollIntoView = ref(bottomAnchorId)

const messages = ref<Message[]>([
  dividerLabel(new Date()),
])

onMounted(() => {
  const userInfoStr = localStorage.getItem('userInfo') || '{}'
  const userInfo = JSON.parse(userInfoStr)
  chatConversationsPost(userInfo?.data?.usnam).then((res) => {
    if (res.data.data.length > 0){
      conversationId.value = res.data.data[0].id
      messagesGet(userInfo?.data?.usnam, res.data.data[0].id).then((res) => {
        res.data.data.forEach((item, index) => {
          messages.value.push(textMsg(item.query, 'me'))
          messages.value.push(textMsg(item.answer, 'bot'))
        });
      })
    }
  })
  scrollToBottom()
})

/** ------------ 工具方法 ------------ **/
function uid(prefix = 'm') {
  return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`
}
function textMsg(text: string, from: From): TextMsg {
  return { id: uid('t'), type: 'text', text, from, time: Date.now() }
}
function resMsg(list: ResItem[], from: From): ResMsg {
  return { id: uid('r'), type: 'resources', resources: list, from, time: Date.now() }
}
function dividerLabel(d: Date): DividerMsg {
  const y = d.getFullYear()
  const m = d.getMonth() + 1
  const day = d.getDate()
  return { id: uid('d'), type: 'divider', label: `${y}-${String(m).padStart(2,'0')}-${String(day).padStart(2,'0')}` }
}
function ensureDayDivider(arr: Message[]) {
  // 若当天没有分割线则补
  const today = new Date()
  const label = `${today.getFullYear()}-${String(today.getMonth()+1).padStart(2,'0')}-${String(today.getDate()).padStart(2,'0')}`
  const has = arr.some(m => m.type === 'divider' && m.label === label)
  if (!has) arr.push(dividerLabel(today))
}
function formatTime(ts: number) {
  const d = new Date(ts)
  const hh = String(d.getHours()).padStart(2,'0')
  const mm = String(d.getMinutes()).padStart(2,'0')
  return `${hh}:${mm}`
}
function scrollToBottom() {
  nextTick(() => { scrollIntoView.value = bottomAnchorId })
}
/** 在顶部插入历史并保持首条可见，避免跳动 */
async function prependHistory(list: Message[]) {
  const firstId = messages.value[0]?.id
  messages.value = [...list, ...messages.value]
  await nextTick()
  if (firstId) scrollIntoView.value = firstId
}

/** ------------ 事件处理 ------------ **/
// const onLoadHistory = () => {
//   if (isLoadingHistory.value) return
// }
// const onPullToRefresh = () => {
//   refresher.value = true
//   setTimeout(async () => {
//     await onLoadHistory()
//     refresher.value = false
//   }, 400)
// }

const openLink = (url: string) => {
  uni.navigateTo({ url: `/pages/webview/index?url=${encodeURIComponent(url)}` })
}

function quickInsert(s: string) {
  input.value += s
}

const sendMessage = async () => {
  if (sending.value) return
  const content = input.value.trim()
  if (!content) return

  sending.value = true

  // 自己消息
  ensureDayDivider(messages.value)
  messages.value.push(textMsg(content, 'me'))
  input.value = ''
  scrollToBottom()

  // 打字中占位
  const typingId = uid('typing')
  messages.value.push({ id: typingId, type: 'typing' })
  scrollToBottom()

  
  try {
    const userInfoStr = localStorage.getItem('userInfo') || '{}'
    const userInfo = JSON.parse(userInfoStr)
    chatMessagesPost(userInfo?.data?.usnam, content, conversationId.value).then((res) => {
      if (res.data) {
        // messages.value.push(
        //   resMsg(res.data.answer, 'bot')
        // )
        messages.value.push(textMsg(res.data.answer, 'bot'))
      } else {
        messages.value.push(textMsg(res.reply || '没有收到有效回复。', 'bot'))
      }
    })

    // 移除“打字中”提示
    messages.value = messages.value.filter(m => m.id !== typingId)
  } catch (err) {
    // 错误处理
    messages.value = messages.value.filter(m => m.id !== typingId)
    messages.value.push(
      textMsg('抱歉，网络出错，无法获取回复。', 'bot')
    )
    console.error('Failed to send message:', err)
  } finally {
    scrollToBottom()
    sending.value = false
  }


  // 模拟服务端响应
  // setTimeout(() => {
  //   // 移除打字中
  //   messages.value = messages.value.filter(m => m.id !== typingId)

  //   if (content.includes('学习资源')) {
  //     messages.value.push(
  //       resMsg([
  //         {
  //           title: 'Vue3 官方文档',
  //           description: '学习 Composition API、响应式系统等核心概念。',
  //           link: 'https://vuejs.org',
  //           cover: 'https://img.vuejs.org/logo.png'
  //         },
  //         {
  //           title: 'uni-app 官方文档',
  //           description: '了解小程序 & H5 跨平台开发框架。',
  //           link: 'https://uniapp.dcloud.io'
  //         },
  //         {
  //           title: '前端工程化指南',
  //           description: '深入理解打包构建、CI/CD 和模块管理。',
  //           link: 'https://juejin.cn/post/6844904094281236493'
  //         },
  //       ], 'bot')
  //     )
  //   } else {
  //     // ✅ 修复原来的类型错误：这里应该是 text，而不是 resources
  //     messages.value.push(textMsg(`你说的是：“${content}”？`, 'bot'))
  //   }
  //   scrollToBottom()
  //   sending.value = false
  // }, 600)
}
</script>

<style lang="scss" scoped>

/* 过渡动画 */
.fade-enter-active, .fade-leave-active { transition: all .18s ease; }
.fade-enter-from { opacity: 0; transform: translateY(4px); }
.fade-leave-to   { opacity: 0; transform: translateY(-4px); }

/* 气泡基础 */
.bubble { position: relative; word-break: break-word; }

/* 打字中动画 */
.typing { display: flex; gap: 4px; align-items: center; }
.dot {
  width: 6px; height: 6px; border-radius: 9999px; background: #c8cdd6;
  animation: blink 1.2s infinite ease-in-out;
}
.dot:nth-child(2){ animation-delay: .15s; }
.dot:nth-child(3){ animation-delay: .3s; }
@keyframes blink {
  0%, 80%, 100% { opacity: .3; transform: translateY(0); }
  40% { opacity: 1; transform: translateY(-2px); }
}

/* 输入区按钮 */
.tool-btn {
  background: #f2f3f5; padding: 6px 10px; border-radius: 10px; font-size: 14px;
}
.send-btn {
  background: #2563eb; color: #fff; padding: 8px 14px; border-radius: 14px; font-size: 14px;
}
.send-btn[disabled] { opacity: .6; }

/* 资源卡片文字省略 */
.line-clamp-1{ display:-webkit-box; -webkit-line-clamp:1; -webkit-box-orient:vertical; overflow:hidden; }
.line-clamp-2{ display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }

/* 输入区整体布局 */
.composer {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 8px 12px;
}

/* 工具按钮行 */
.tools-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* 主输入行：输入框 + 发送按钮 */
.composer-main {
  display: flex;
  align-items: flex-end;
  gap: 8px;
}

/* 多行输入框：与按钮高度协调 */
.composer-input {
  flex: 1;
  background: #fff;
  border: 1px solid #e5e7eb; /* gray-200 */
  border-radius: 16px;
  padding: 10px 12px;
  min-height: 33px;
  max-height: 66px;
  line-height: 1.4;
  font-size: 14px;
  /* 兼容性兜底：在部分端 textarea 默认背景为透明 */
  box-sizing: border-box;
  border-radius: 6px !important;
}

/* ---------- wd-button 外观微调（scoped 下使用 :deep） ---------- */

/* 工具按钮：小巧、圆角、发丝描边 */
:deep(.wd-tool-btn.wd-button) {
  min-height: 22px;             /* 提升触控面积 */
  border-radius: 6px !important;
}

:deep(.wd-tool-btn .wd-button__content) {
  padding: 0 10px;               /* 内容内边距 */
  font-size: 14px;
}

/* 发送按钮：更显主按钮特征 */
:deep(.wd-send-btn.wd-button) {
  min-height: 55px;
  border-radius: 6px !important;
}

:deep(.wd-send-btn.is-disabled) {
  opacity: .6;                   /* 禁用态 */
}

/* 统一按钮文本不换行，避免高度抖动 */
:deep(.wd-button .wd-button__content) {
  white-space: nowrap;
}
</style>
